package com.yang.staff.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yang.staff.mapper.DepartmentMapper;
import com.yang.staff.mapper.StaffMapper;
import com.yang.staff.pojo.Department;
import com.yang.staff.pojo.Staff;
import com.yang.staff.service.StaffService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.*;

@Service
public class StaffServiceImpl extends ServiceImpl<StaffMapper, Staff> implements StaffService {

    /**
     * 注入秘钥
     */
    @Value("${secret}")
    private String secret;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private BCryptPasswordEncoder encoder;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    RestHighLevelClient client;

    @Override
    public Map<String, Object> login(Staff staff) {
        Map<String, Object> map = new HashMap<String, Object>();
        QueryWrapper<Staff> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", staff.getUserName());
        Staff s = this.staffMapper.selectOne(wrapper);
        if (s != null) {
            if (encoder.matches(staff.getPwd(), s.getPwd())) {
                // 把员工信息加密生成token存入map
                Map<String, Object> m = new HashMap<String, Object>();
                m.put("id", s.getId());
                m.put("name", s.getName());
                m.put("did", s.getDid());
                m.put("user_name", s.getUserName());
                String token = Jwts.builder().setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256, secret).setClaims(m).compact();
                map.put("flag", true);
                map.put("token", token);
                return map;
            }
        }
        map.put("flag", false);
        map.put("message", "用户名或密码错误");
        return map;
    }

    @Override
    public Staff decodingToken(String token) {
        Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        Staff staff = new Staff();
        staff.setId((Integer) claims.get("id"));
        staff.setName((String) claims.get("name"));
        staff.setUserName((String) claims.get("user_name"));
        staff.setDid((Integer) claims.get("did"));
        return staff;
    }

    @Override
    public Map<String, Object> friendList(Staff staff) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (staff == null) {
            map.put("flag", false);
            map.put("msg", "验签失败");
        }
        QueryWrapper<Staff> wrapper = new QueryWrapper<>();
        wrapper.ne("id", staff.getId());
        Page<Staff> staffPage = new Page<Staff>(1, 10);
        staffMapper.selectPage(staffPage, wrapper);

        map.put("list", staffPage.getRecords());
        map.put("total", staffPage.getTotal());
        map.put("flag", true);
        return map;
    }

    @Override
    @Transactional
    public Boolean register(Staff staff) {
        String encode = encoder.encode(staff.getPwd());
        staff.setPwd(encode);
        if (this.save(staff)) {
            return true;
        }
        return false;
    }

    @Override
    public List<Department> departments() {
        return departmentMapper.selectList(null);
    }

    @Override
    public void sendMes(String s1) {
        amqpTemplate.convertAndSend("words_prohibit", s1);
    }

    @Override
    public List<Map> wordsProhibit() {
        // elasticsearch搜索
        String[] wordsProhibits = {"韬叔", "八嘎", "牛马"};

        SearchRequest searchRequest = new SearchRequest("words");
        searchRequest.types("words_prohibit");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //先定义一个MultiMatchQuery
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery(wordsProhibits[2], "message")
                    .minimumShouldMatch("50%")
                    .field("name", 10));


        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<tag>");
        highlightBuilder.postTags("</tag>");
        highlightBuilder.fields().add(new HighlightBuilder.Field("message"));
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);
        List<Map> list = new ArrayList<Map>();
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] hits = searchResponse.getHits().getHits();

            for (SearchHit hit : hits) {
                //文档的主键
                String id = hit.getId();
                //源文档内容
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                //源文档的name字段内容
                String message = (String) sourceAsMap.get("message");
                //取出高亮字段
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                //取出name高亮字段
                HighlightField nameHighlightField = highlightFields.get("message");
                if (nameHighlightField != null) {
                    Text[] fragments = nameHighlightField.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for (Text text : fragments) {
                        stringBuffer.append(text);
                    }
                    message = stringBuffer.toString();
                    sourceAsMap.put("message", message);
                }
                list.add(sourceAsMap);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }
}
